﻿// OneScript: ./OInt/core/Modules/OPI_Twitter.os
// Lib: Twitter
// CLI: twitter

// MIT License

// Copyright (c) 2023 Anton Tsitavets

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// https://github.com/Bayselonarrend/OpenIntegrations
// Если в не знаете с чего начать, то стоит найти метод ПолучитьСтандартныеПараметры()
// и почитать комментарии

// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off

//@skip-check method-too-many-params
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content

// Раскомментировать, если выполняется OneScript
#Использовать "../../tools"

#Область ПрограммныйИнтерфейс

#Область ДанныеИНастройка

// Получить ссылку для авторизации
// Формирует ссылку для авторизации через браузер
// 
// Параметры:
//  Параметры  - Структура из Строка - См.ПолучитьСтандартныеПараметры - auth - JSON авторизации или путь к .json
// 
// Возвращаемое значение:
//  Строка -  URL для перехода в браузере
Функция ПолучитьСсылкуАвторизации(Параметры = "") Экспорт
    
    Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
    
    ПараметрыURL = Новый Структура;
        
    ПараметрыURL.Вставить("response_type"        , "code");
    ПараметрыURL.Вставить("client_id"            , Параметры_["client_id"]);
    ПараметрыURL.Вставить("redirect_uri"         , Параметры_["redirect_uri"]);
    ПараметрыURL.Вставить("scope"                , Параметры_["scope"]);
    ПараметрыURL.Вставить("state"                , "state");
    ПараметрыURL.Вставить("code_challenge"       , "challenge");
    ПараметрыURL.Вставить("code_challenge_method", "plain");
        
    ПараметрыURL = OPI_Инструменты.ПараметрыЗапросаВСтроку(ПараметрыURL);
    Линк = "https://twitter.com/i/oauth2/authorize" + ПараметрыURL;
        
    Возврат Линк;
    
КонецФункции

// Получить токен
// Получает токен по коду, полученному при авторизации по ссылке из ПолучитьСсылкуАвторизации
// 
// Параметры:
//  Код        - Строка              - Код, полученный из авторизации См.ПолучитьСсылкуАвторизации - code
//  Параметры  - Структура из Строка - См.ПолучитьСтандартныеПараметры - auth - JSON авторизации или путь к .json
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция ПолучитьТокен(Знач Код, Знач Параметры = "") Экспорт

    OPI_ПреобразованиеТипов.ПолучитьСтроку(Код);
        
    Параметры_ = ПолучитьСтандартныеПараметры(Параметры);

    ПараметрыЗапроса = Новый Структура;
    ПараметрыЗапроса.Вставить("code"         , Код);
    ПараметрыЗапроса.Вставить("grant_type"   , "authorization_code");
    ПараметрыЗапроса.Вставить("client_id"    , Параметры_["client_id"]);
    ПараметрыЗапроса.Вставить("redirect_uri" , Параметры_["redirect_uri"]);
    ПараметрыЗапроса.Вставить("code_verifier", "challenge");
    
    Ответ = OPI_Инструменты.Post("https://api.twitter.com/2/oauth2/token"
        , ПараметрыЗапроса, , Ложь);
        
    Возврат Ответ;
    
КонецФункции

// Обновить токен 
// Обновляет v2 токен при помощи refresh_token
// 
// Параметры:
//  Параметры  - Структура из Строка - См.ПолучитьСтандартныеПараметры - auth - JSON авторизации или путь к .json
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция ОбновитьТокен(Знач Параметры = "") Экспорт
    
    Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
    Refresh    = "refresh_token";
    
    ПараметрыЗапроса = Новый Структура;
    ПараметрыЗапроса.Вставить(Refresh        , Параметры_[Refresh]);
    ПараметрыЗапроса.Вставить("grant_type"   , Refresh);
    ПараметрыЗапроса.Вставить("client_id"    , Параметры_["client_id"]);
    
    Ответ = OPI_Инструменты.Post("https://api.twitter.com/2/oauth2/token"
    , ПараметрыЗапроса, , Ложь);
    
    Возврат Ответ;

КонецФункции

// !NOCLI
// Метод для вставки в http-сервис, адрес которого указывается в redirect_uri
// Вызывает метод получения токена, так как для получения токена из кода, приходящего
// на redirect_uri после авторизации через браузер есть всего 30 секунд
// 
// Параметры:
//  Запрос - HTTPСервисЗапрос - Запрос, приходящий на http-сервис
// 
// Возвращаемое значение:
//  HTTPОтвет, Произвольный, ДвоичныеДанные - Результат чтения JSON ответа сервера
Функция ОбработкаВходящегоЗапросаПослеАвторизации(Запрос) Экспорт
    
    Код         = Запрос.ПараметрыЗапроса["code"];    
    ОтветТокен  = ПолучитьТокен(Код);
    
    // BSLLS:CommentedCode-off
    // Предпочтительное хранение токенов
    // Константы.TwitterRefresh.Установить(ОтветТокен["refresh_token"]);
    // Константы.TwitterToken.Установить(ОтветТокен["access_token"]);
    // BSLLS:CommentedCode-on
    
    Возврат ОтветТокен;

КонецФункции

#КонецОбласти

#Область Твиты

// !NOCLI
// Создать произвольный твит
// 
// Параметры:
//  Текст - Строка        -  Текст твита
//  МассивМедиа           -  Массив из Строка,ДвоичныеДанные -  Массив двоичных данных или путей к файлам
//  МассивВариантовОпроса - Массив из Строка -  Массив вариантов опроса, если необходимо
//  ДлительностьОпроса    - Строка,Число -  Длительность опроса, если необходимо (опрос без длительности не создается)
//  Параметры  - Структура из Строка - См.ПолучитьСтандартныеПараметры - auth - JSON авторизации или путь к .json
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьПроизвольныйТвит(Знач Текст = ""
    , Знач МассивМедиа = ""
    , Знач МассивВариантовОпроса = ""
    , Знач ДлительностьОпроса = ""
    , Знач Параметры = "") Экспорт 
    
    OPI_ПреобразованиеТипов.ПолучитьСтроку(Текст);
    OPI_ПреобразованиеТипов.ПолучитьСтроку(ДлительностьОпроса);
    
    Если ЗначениеЗаполнено(МассивМедиа) Тогда
        OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивМедиа);
    КонецЕсли;
    
    Если ЗначениеЗаполнено(МассивВариантовОпроса) Тогда
        OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивВариантовОпроса);
    КонецЕсли;
    
    Параметры_         = ПолучитьСтандартныеПараметры(Параметры);
    URL                = "https://api.twitter.com/2/tweets";
    Массив             = "Массив";    
    Поля               = Новый Соответствие;
    
    Если ЗначениеЗаполнено(Текст) Тогда
        Поля.Вставить("text", Текст);
    КонецЕсли;
    
    Если ТипЗнч(МассивВариантовОпроса) = Тип(Массив) И ЗначениеЗаполнено(ДлительностьОпроса) Тогда
        
        ДлительностьОпроса = Число(ДлительностьОпроса);
        
        Если МассивВариантовОпроса.Количество() > 0 Тогда
        	
        	СтруктураВарианта = Новый Структура("options,duration_minutes", МассивВариантовОпроса, ДлительностьОпроса);
            Поля.Вставить("poll", СтруктураВарианта);
            
        КонецЕсли;
        
    КонецЕсли;
    
    Если ТипЗнч(МассивМедиа) = Тип(Массив) Тогда
        Если МассивМедиа.Количество() > 0 Тогда
            Поля.Вставить("media", Новый Структура("media_ids", МассивМедиа));
        КонецЕсли;
    КонецЕсли;
    
    Авторизация = СоздатьЗаголовокАвторизацииV2(Параметры_);
    Ответ       = OPI_Инструменты.Post(URL, Поля, Авторизация);

    Возврат Ответ;
    
КонецФункции

// Создать текстовый твит
// Создает твит без вложений
// 
// Параметры:
//  Текст      - Строка              - Текст твита                     - text
//  Параметры  - Структура из Строка - См.ПолучитьСтандартныеПараметры - auth - JSON авторизации или путь к .json
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТекстовыйТвит(Знач Текст, Знач Параметры = "") Экспорт
    Возврат СоздатьПроизвольныйТвит(Текст, , , , Параметры);    
КонецФункции

// Создать твит картинки
// Создает твит с картинкой вложением
// 
// Параметры:
//  Текст          - Строка                          - Текст твита            - text
//  МассивКартинок - Массив из Строка,ДвоичныеДанные - Массив файлов картинок - pictures
//  Параметры  - Структура из Строка - См.ПолучитьСтандартныеПараметры - auth - JSON авторизации или путь к .json
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТвитКартинки(Знач Текст, Знач МассивКартинок, Знач Параметры = "") Экспорт
    
    МассивМедиа = ЗагрузитьМассивВложений(МассивКартинок, "photo", Параметры);
    Возврат СоздатьПроизвольныйТвит(Текст, МассивМедиа, , , Параметры);    
    
КонецФункции

// Создать твит гифки
// Создает твит с вложением-гифкой
// 
// Параметры:
//  Текст       - Строка                          - Текст твита         - text
//  МассивГифок - Массив из Строка,ДвоичныеДанные - Массив файлов гифок - gifs
//  Параметры   - Структура из Строка - См.ПолучитьСтандартныеПараметры - auth - JSON авторизации или путь к .json
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТвитГифки(Знач Текст, Знач МассивГифок, Знач Параметры = "") Экспорт
    
    МассивМедиа = ЗагрузитьМассивВложений(МассивГифок, "animated_gif", Параметры);
    Возврат СоздатьПроизвольныйТвит(Текст, МассивМедиа, , , Параметры);    
    
КонецФункции

// Создать твит видео
// Создает твит с видеовложением
// 
// Параметры:
//  Текст       - Строка                          - Текст твита         - text
//  МассивВидео - Массив из Строка,ДвоичныеДанные - Массив файлов видео - videos
//  Параметры   - Структура из Строка - См.ПолучитьСтандартныеПараметры - auth - JSON авторизации или путь к .json
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТвитВидео(Знач Текст, Знач МассивВидео, Знач Параметры = "") Экспорт
    
    МассивМедиа = ЗагрузитьМассивВложений(МассивВидео, "video", Параметры);
    Возврат СоздатьПроизвольныйТвит(Текст, МассивМедиа, , , Параметры);
    
КонецФункции

// Создать твит опрос
// Создает твит с опросом
// 
// Параметры:
//  Текст           - Строка           - Текст твита               - text
//  МассивВариантов - Массив из Строка - Массив вариантов опроса   - options
//  Длительность    - Строка,Число     - Длительность опроса       - duration
//  Параметры  - Структура из Строка - См.ПолучитьСтандартныеПараметры - auth - JSON авторизации или путь к .json
// 
// Возвращаемое значение:
//  Соответствие Из КлючИЗначение - сериализованный JSON ответа от Twitter
Функция СоздатьТвитОпрос(Знач Текст, Знач МассивВариантов, Знач Длительность, Знач Параметры = "") Экспорт
	
    Возврат СоздатьПроизвольныйТвит(Текст, , МассивВариантов, Длительность, Параметры);    
    
КонецФункции

// Загрузить массив вложений !NOCLI
// Загружает файлы на сервер и возвращает их ID
// 
// Параметры:
//  МассивФайлов - Массив из Строка, ДвоичныеДанные -  Массив файлов
//  ТипВложений  - Строка -  Тип вложений
//  Параметры    - Структура из Строка - См.ПолучитьСтандартныеПараметры - auth - JSON авторизации или путь к .json
// 
// Возвращаемое значение:
//  Массив Из Строка -  Массив ID медиа
Функция ЗагрузитьМассивВложений(Знач МассивФайлов, Знач ТипВложений, Знач Параметры = "") Экспорт
    
    OPI_ПреобразованиеТипов.ПолучитьСтроку(ТипВложений);
    OPI_ПреобразованиеТипов.ПолучитьКоллекцию(МассивФайлов);
    
    МассивМедиа = Новый Массив;
    Параметры_  = ПолучитьСтандартныеПараметры(Параметры);
    MIS         = "media_id_string";
    
    Если ЗначениеЗаполнено(МассивФайлов) Тогда
                 
        Для Каждого ФайлОтправки Из МассивФайлов Цикл
                       
            OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(ФайлОтправки);
            
            Ответ   = ЗагрузитьМедиафайл(ФайлОтправки, ТипВложений, Параметры_);
            IDМедиа = Ответ[MIS];
            
            Если Не ЗначениеЗаполнено(IDМедиа) Тогда
                Возврат Ответ;
            КонецЕсли;
            
            МассивМедиа.Добавить(IDМедиа);
            
        КонецЦикла;
    
    КонецЕсли;
        
    Возврат МассивМедиа;
    
КонецФункции

#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

Функция ЗагрузитьМедиафайл(Знач Файл, Знач Тип, Знач Параметры) 
   
    OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Файл);
   
    ВидЗапроса = "POST";    
    Параметры_ = ПолучитьСтандартныеПараметры(Параметры);
    URL        = "https://upload.twitter.com/1.1/media/upload.json";
     
    Если Тип = "photo" Тогда 
        
        Поля = Новый Структура;
        Поля.Вставить("media_data"    , Base64Строка(Файл));
        Поля.Вставить("media_category", Тип);
        
        Авторизация = СоздатьЗаголовокАвторизацииV1(Параметры_, Поля, ВидЗапроса, URL);        
        Ответ       = OPI_Инструменты.Post(URL, Поля, Авторизация, Ложь);
        
    Иначе
        
        Ответ = ЗагрузитьМедиаЧастями(Файл, Тип, ВидЗапроса, URL, Параметры_);
        
    КонецЕсли;
    
    Возврат Ответ;
    
КонецФункции

Функция ЗагрузитьМедиаЧастями(Знач Файл, Знач Тип, Знач ВидЗапроса, Знач URL, Параметры)
    
    Единица          = 1024;
    Количество       = 4;
    MediaKey         = "media_key";
    MIS              = "media_id_string";
    Command          = "command";
    Размер           = Файл.Размер();
    
    СоответствиеMIME = Новый Соответствие;
    СоответствиеMIME.Вставить("photo"       , "image/jpeg");
    СоответствиеMIME.Вставить("video"       , "video/mp4");
    СоответствиеMIME.Вставить("animated_gif", "image/gif");
    
    РазмерЧасти  = Количество * Единица * Единица;
    МассивЧтения = РазделитьДвоичныеДанные(Файл, РазмерЧасти);
    
    Поля = Новый Структура;
    Поля.Вставить(Command          , "INIT");
    Поля.Вставить("total_bytes"    , OPI_Инструменты.ЧислоВСтроку(Размер));
    Поля.Вставить("media_type"     , СоответствиеMIME.Получить(Тип));
    Поля.Вставить("media_category" , Тип);
    
    Авторизация = СоздатьЗаголовокАвторизацииV1(Параметры, Поля, ВидЗапроса, URL);

    ОтветИнициализации = OPI_Инструменты.Post(URL, Поля, Авторизация, Ложь);
    KeyИнициализации   = ОтветИнициализации[MediaKey];
    IDИнициализации    = ОтветИнициализации[MIS];
    
    Если Не ЗначениеЗаполнено(KeyИнициализации) Или Не ЗначениеЗаполнено(IDИнициализации) Тогда
        Возврат ОтветИнициализации;     
    КонецЕсли;
    
    Счетчик = 0;
    
    Для Каждого Часть Из МассивЧтения Цикл
        
        Поля = Новый Структура;
        Поля.Вставить(Command           , "APPEND");
        Поля.Вставить("media_key"       , KeyИнициализации);
        Поля.Вставить("segment_index"   , OPI_Инструменты.ЧислоВСтроку(Счетчик));
        Поля.Вставить("media"           , Часть);

        Авторизация = СоздатьЗаголовокАвторизацииV1(Параметры, Новый Структура, ВидЗапроса, URL);
        
        OPI_Инструменты.PostMultipart(URL, Поля, , , Авторизация);
        
        Счетчик = Счетчик + 1;
        
    КонецЦикла;
    
    Поля = Новый Структура;
    Поля.Вставить(Command   , "FINALIZE");
    Поля.Вставить("media_id", IDИнициализации);
    
    СтатусОбработки = ПолучитьСтатусОбработки(Параметры, Поля, URL);
    
    Если Не ТипЗнч(СтатусОбработки) = Тип("Строка") Тогда
        Возврат СтатусОбработки;
    КонецЕсли;
            
    Ответ = ОжидатьЗавершенияОбработки(СтатусОбработки, IDИнициализации, URL, Параметры);
    
    Возврат Ответ;
        
КонецФункции

Функция ОжидатьЗавершенияОбработки(Знач СтатусОбработки, Знач IDИнициализации, Знач URL, Знач Параметры)
    
    ProcessingInfo   = "processing_info";
    Command          = "command";
    Поля             = Новый Структура;
    
    Поля.Вставить(Command   , "STATUS");
    Поля.Вставить("media_id", IDИнициализации);

    Пока Строка(СтатусОбработки) = "pending" Или Строка(СтатусОбработки) = "in_progress" Цикл
         
        Авторизация     = СоздатьЗаголовокАвторизацииV1(Параметры, Поля, "GET", URL);        
        Ответ           = OPI_Инструменты.Get(URL, Поля, Авторизация);     
        Информация      = Ответ[ProcessingInfo];

        Если Не ЗначениеЗаполнено(Информация) Тогда
            Возврат Ответ;
        КонецЕсли;
        
        СтатусОбработки = Информация["state"];
        
        Если Не ЗначениеЗаполнено(СтатусОбработки) Тогда
            Возврат Ответ;
        КонецЕсли;
       
    КонецЦикла;
    
    Если СтатусОбработки = "failed" Тогда
        ВызватьИсключение "Твиттер не смог обработать загруженное вами видео";
    КонецЕсли;
    
    Возврат Ответ;
    
КонецФункции

Функция ПолучитьСтандартныеПараметры(Знач Параметры = "")
    
    // Здесь собрано определение данных, необходимых для работы.
    // Для Twitter это довольно значительный набор, что обсуловлено наличием сразу 2-х API,
    // которые, при этом, созданы не для разныз задач, но просто являются версиями друг друга.
    // Актуальной версией API является v2 и она требует получения временных токенов. Несмотря на то,
    // что Twitter настаивает на использовании этой актуальной версии, они как-то умудрились не перенести
    // механизм загрузки файлов и некоторые другие из старой версии - v1.1. Поэтому что-то нужно делать 
    // на версии 1.1, а что-то на 2: вплоть до того что они убрали возможность постить твиты из v1.1,
    // но только через нее в твит можно добавить картинку. При этом способы авторизации и токены у них разные
    
    // Мировая гигокорпорация Илона Маска, кстати, напоминаю ;)
    
    // P.S Далее часто упоминается "страница настроек Twitter Developer" - это 
    // https://developer.twitter.com/en/portal/dashboard и выбор конкретного проекта из списка (значек c ключем)
    
    Параметры_ = Новый Соответствие; 
    Разрешения = "tweet.read tweet.write tweet.moderate.write users.read "
        + "follows.read follows.write offline.access space.read mute.read "
        + "mute.write like.read like.write list.read list.write block.read "
        + "block.write bookmark.read bookmark.write";    
               
    // Данные для API v2
        
    // redirect_uri  - URL вашего http-сервиса (или другого обработчика запросов) для авторизации
    // scope         - набор разрешений для получаемого ключа. Может быть любой, но offline.access обязателен
    // client_id     - Из OAuth 2.0 Client ID and Client Secret страницы настроек Twitter Developer
    // client_secret - Из OAuth 2.0 Client ID and Client Secret страницы настроек Twitter Developer
    // access_token  - ПолучитьСсылкуАвторизации() -> Браузер -> code придет на redirect_uri -> ПолучитьТокен(code)
    // refresh_token - Приходит вместе с access_token и используется для его обновления (время жизни access_token - 2 ч)
    //                 Обновление происходит методом ОбновитьТокен с новыми access_token и refresh_token. 
    //                 При следующем обновлении нужно использовать уже новый refresh_token, так что захардкодить 
    //                 не получится (access_token тоже не получится) 
    
    //           |--> ОбновитьТокен() ->|access_token  --> Используется в т-нии 2-х часов для запросов
    //           |                      |refresh_token --|
    //           |--------[через 2 ч.]-------------------|
     
    // Данные для API v1.1
    
    // oauth_token           - Из Authentication Tokens -> Access Token and Secret страницы настроек Twitter Developer 
    // oauth_token_secret    - Из Authentication Tokens -> Access Token and Secret страницы настроек Twitter Developer
    // oauth_consumer_key    - Из Consumer Keys -> Access Token and Secret страницы настроек Twitter Developer
    // oauth_consumer_secret - Из Consumer Keys -> Access Token and Secret страницы настроек Twitter Developer
    
    // Эти токены обновлять не надо
    
    Параметры_.Вставить("redirect_uri"         , "");
    Параметры_.Вставить("scope"                , Разрешения);
    Параметры_.Вставить("client_id"            , "");
    Параметры_.Вставить("client_secret"        , "");
    Параметры_.Вставить("access_token"         , ""); // Должно быть нечто вроде Константы.TwitterToken.Получить()
    Параметры_.Вставить("refresh_token"        , ""); // Должно быть нечто вроде Константы.TwitterRefresh.Получить()
    Параметры_.Вставить("oauth_token"          , "");
    Параметры_.Вставить("oauth_token_secret"   , "");
    Параметры_.Вставить("oauth_consumer_key"   , "");
    Параметры_.Вставить("oauth_consumer_secret", "");
    
    OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Параметры);
    
    Если ТипЗнч(Параметры) = Тип("Структура") Или ТипЗнч(Параметры) = Тип("Соответствие") Тогда
        Для Каждого ПереданныйПараметр Из Параметры Цикл
            Параметры_.Вставить(ПереданныйПараметр.Ключ, OPI_Инструменты.ЧислоВСтроку(ПереданныйПараметр.Значение));
        КонецЦикла;
    КонецЕсли;

    Возврат Параметры_;

КонецФункции

Функция СоздатьЗаголовокАвторизацииV1(Знач Параметры, Знач Поля, Знач ВидЗапроса, Знач URL)
    
    ТекущаяДата          = OPI_Инструменты.ПолучитьТекущуюДату();
    ЗаголовокАвторизации = "";
    МетодХэширования     = "HMAC-SHA1";
    ВерсияАпи            = "1.0";
    СтрокаСигнатуры      = "";
    Подпись              = "";
    OCK                  = "oauth_consumer_key";
    OTK                  = "oauth_token";
    ТекущаяДатаUNIX      = OPI_Инструменты.UNIXTime(ТекущаяДата);
    ТекущаяДатаUNIX      = OPI_Инструменты.ЧислоВСтроку(ТекущаяДатаUNIX);
    ТаблицаПараметров    = Новый ТаблицаЗначений;
    ТаблицаПараметров.Колонки.Добавить("Ключ");
    ТаблицаПараметров.Колонки.Добавить("Значение");
        
    Для Каждого Поле Из Поля Цикл 
        
        НоваяСтрока = ТаблицаПараметров.Добавить();    
        НоваяСтрока.Ключ     = Поле.Ключ;
        НоваяСтрока.Значение = Поле.Значение;
        
    КонецЦикла;
    
    НоваяСтрока = ТаблицаПараметров.Добавить();
    НоваяСтрока.Ключ     = OCK;
    НоваяСтрока.Значение = Параметры[OCK];
    
    НоваяСтрока = ТаблицаПараметров.Добавить();
    НоваяСтрока.Ключ     = OTK;
    НоваяСтрока.Значение = Параметры[OTK];
    
    НоваяСтрока = ТаблицаПараметров.Добавить();
    НоваяСтрока.Ключ     = "oauth_version";
    НоваяСтрока.Значение = ВерсияАпи;
    
    НоваяСтрока = ТаблицаПараметров.Добавить();
    НоваяСтрока.Ключ     = "oauth_signature_method";
    НоваяСтрока.Значение = МетодХэширования;

    НоваяСтрока = ТаблицаПараметров.Добавить();
    НоваяСтрока.Ключ     = "oauth_timestamp";
    НоваяСтрока.Значение = ТекущаяДатаUNIX;

    НоваяСтрока = ТаблицаПараметров.Добавить();
    НоваяСтрока.Ключ     = "oauth_nonce";
    НоваяСтрока.Значение = ТекущаяДатаUNIX;

    Для Каждого СтрокаТаблицы Из ТаблицаПараметров Цикл
        
        СтрокаТаблицы.Ключ     = КодироватьСтроку(СтрокаТаблицы.Ключ, СпособКодированияСтроки.КодировкаURL);
        СтрокаТаблицы.Значение = КодироватьСтроку(СтрокаТаблицы.Значение, СпособКодированияСтроки.КодировкаURL);
        
    КонецЦикла;
    
    ТаблицаПараметров.Сортировать("Ключ");
    
    Для Каждого СтрокаТаблицы Из ТаблицаПараметров Цикл
        
        СтрокаСигнатуры = СтрокаСигнатуры 
            + СтрокаТаблицы.Ключ 
            + "="
            + СтрокаТаблицы.Значение
            + "&";
            
    КонецЦикла;
    
    СтрокаСигнатуры = Лев(СтрокаСигнатуры, СтрДлина(СтрокаСигнатуры) - 1);
    СтрокаСигнатуры = вРег(ВидЗапроса) 
        + "&" 
        + КодироватьСтроку(URL, СпособКодированияСтроки.КодировкаURL)
        + "&"
        + КодироватьСтроку(СтрокаСигнатуры, СпособКодированияСтроки.КодировкаURL);
        
    Подпись = КодироватьСтроку(Параметры["oauth_consumer_secret"], СпособКодированияСтроки.КодировкаURL)
        + "&" 
        + КодироватьСтроку(Параметры["oauth_token_secret"], СпособКодированияСтроки.КодировкаURL);
             
    Сигнатура = OPI_Криптография.HMAC(ПолучитьДвоичныеДанныеИзСтроки(Подпись)
        , ПолучитьДвоичныеДанныеИзСтроки(СтрокаСигнатуры)
        , ХешФункция.SHA1
        , 64);
        
    Сигнатура = КодироватьСтроку(Base64Строка(Сигнатура), СпособКодированияСтроки.КодировкаURL);
    
    Разделитель          = """,";
    ЗаголовокАвторизации = ЗаголовокАвторизации 
        + "OAuth "
        + "oauth_consumer_key="""      + Параметры[OCK]        + Разделитель
        + "oauth_token="""             + Параметры[OTK]        + Разделитель
        + "oauth_signature_method="""  + МетодХэширования      + Разделитель
        + "oauth_timestamp="""         + ТекущаяДатаUNIX       + Разделитель
        + "oauth_nonce="""             + ТекущаяДатаUNIX       + Разделитель
        + "oauth_version="""           + ВерсияАпи             + Разделитель
        + "oauth_signature="""         + Сигнатура;
        
        СоответствиеЗаголовка = Новый Соответствие;
        СоответствиеЗаголовка.Вставить("authorization", ЗаголовокАвторизации);
        
    Возврат СоответствиеЗаголовка;
        
КонецФункции

Функция СоздатьЗаголовокАвторизацииV2(Знач Параметры)
    
    СоответствиеВозврата = Новый Соответствие;
    СоответствиеВозврата.Вставить("Authorization", "Bearer " + Параметры["access_token"]);
    
    Возврат СоответствиеВозврата;
    
КонецФункции

Функция ПолучитьСтатусОбработки(Знач Параметры, Знач Поля, Знач URL)

	ProcessingInfo   = "processing_info";
    Авторизация = СоздатьЗаголовокАвторизацииV1(Параметры, Поля, "POST", URL);
    
    Ответ      = OPI_Инструменты.Post(URL, Поля, Авторизация, Ложь);  
    Информация = Ответ[ProcessingInfo];
    
    Если Не ЗначениеЗаполнено(Информация) Тогда
    	Возврат Ответ;
    КонецЕсли;
    
    СтатусОбработки = Информация["state"];
    
    Если Не ЗначениеЗаполнено(СтатусОбработки) Тогда
    	Возврат Ответ;
    Иначе
    	Возврат СтатусОбработки;
    КонецЕсли;	
    
КонецФункции

#КонецОбласти
